Improve binding-set parser
authorMatthias Clasen <mclasen@redhat.com>
Sat, 29 Jan 2011 00:36:24 +0000 (19:36 -0500)
committerMatthias Clasen <mclasen@redhat.com>
Mon, 31 Jan 2011 02:27:56 +0000 (21:27 -0500)
Make gtk_binding_entry_add_signal_from_string() return the expected
token in case of parsing error, so that we can return a GError
instead of spewing. Also, add a separate scope for binding-set,
since allowing {} in identifiers in SCOPE_VALUE breaks the fact
that the ; after the last assignment in a rule is optional.

gtk/gtkbindings.c
gtk/gtkbindings.h
gtk/gtkcssprovider.c

index 2b9d51230fc268e973d816a9a6bf078505e607e9..ef31fb97461f7c27cc7acfd2983aa4f258d010e0 100644 (file)
@@ -1271,17 +1271,20 @@ create_signal_scanner (void)
  * Key combinations must be in a format that can be parsed by
  * gtk_accelerator_parse().
  *
+ * Returns: %G_TOKEN_NONE if the signal was successfully parsed and added,
+ *     the expected token otherwise
+ *
  * Since: 3.0
- **/
-void
+ */
+GTokenType
 gtk_binding_entry_add_signal_from_string (GtkBindingSet *binding_set,
-                                         const gchar   *signal_desc)
+                                          const gchar   *signal_desc)
 {
   static GScanner *scanner = NULL;
   GTokenType ret;
 
-  g_return_if_fail (binding_set != NULL);
-  g_return_if_fail (signal_desc != NULL);
+  g_return_val_if_fail (binding_set != NULL, G_TOKEN_NONE);
+  g_return_val_if_fail (signal_desc != NULL, G_TOKEN_NONE);
 
   if (G_UNLIKELY (!scanner))
     scanner = create_signal_scanner ();
@@ -1291,12 +1294,10 @@ gtk_binding_entry_add_signal_from_string (GtkBindingSet *binding_set,
 
   ret = gtk_binding_parse_bind (scanner, binding_set);
 
-  if (ret != G_TOKEN_NONE)
-    g_scanner_unexp_token (scanner, ret, NULL, NULL, NULL,
-                           "Could not parse binding", FALSE);
-
   /* Reset for next use */
   g_scanner_set_scope (scanner, 0);
+
+  return ret;
 }
 
 /**
index 4529567a6cc6251f147e158ca5b34e31ac305e7f..cf7f6bfb145fcf4e48eeb9aebfb2c7730e13c495 100644 (file)
@@ -125,8 +125,8 @@ void         gtk_binding_entry_add_signall  (GtkBindingSet  *binding_set,
                                         const gchar    *signal_name,
                                         GSList         *binding_args);
 
-void     gtk_binding_entry_add_signal_from_string (GtkBindingSet *binding_set,
-                                                  const gchar   *signal_desc);
+GTokenType gtk_binding_entry_add_signal_from_string (GtkBindingSet *binding_set,
+                                                     const gchar   *signal_desc);
 
 void    gtk_binding_entry_remove       (GtkBindingSet  *binding_set,
                                         guint           keyval,
index a0992f740a22090733497d8ece2a97112033a924..b43d52f7cd261234ac070a0bd8ba8ff228fd5e88 100644 (file)
@@ -801,7 +801,8 @@ enum ParserScope {
   SCOPE_PSEUDO_CLASS,
   SCOPE_NTH_CHILD,
   SCOPE_DECLARATION,
-  SCOPE_VALUE
+  SCOPE_VALUE,
+  SCOPE_BINDING_SET
 };
 
 /* Extend GtkStateType, since these
@@ -1505,6 +1506,12 @@ scanner_apply_scope (GScanner    *scanner,
   g_scanner_set_scope (scanner, scope);
 
   if (scope == SCOPE_VALUE)
+    {
+      scanner->config->cset_identifier_first = G_CSET_a_2_z G_CSET_A_2_Z G_CSET_DIGITS "@#-_";
+      scanner->config->cset_identifier_nth = G_CSET_a_2_z G_CSET_A_2_Z G_CSET_DIGITS "@#-_ +(),.%\t\n'/\"";
+      scanner->config->scan_identifier_1char = TRUE;
+    }
+  else if (scope == SCOPE_BINDING_SET)
     {
       scanner->config->cset_identifier_first = G_CSET_a_2_z G_CSET_A_2_Z G_CSET_DIGITS "@#-_";
       scanner->config->cset_identifier_nth = G_CSET_a_2_z G_CSET_A_2_Z G_CSET_DIGITS "@#-_ +(){}<>,.%\t\n'/\"";
@@ -3318,19 +3325,27 @@ parse_rule (GtkCssProvider  *css_provider,
           if (scanner->token != G_TOKEN_LEFT_CURLY)
             return G_TOKEN_LEFT_CURLY;
 
-          css_provider_push_scope (css_provider, SCOPE_VALUE);
+          css_provider_push_scope (css_provider, SCOPE_BINDING_SET);
           g_scanner_get_next_token (scanner);
 
           do
             {
+              GTokenType ret;
+
               if (scanner->token != G_TOKEN_IDENTIFIER)
                 {
                   scanner->user_data = "Binding definition";
                   return G_TOKEN_IDENTIFIER;
                 }
 
-              gtk_binding_entry_add_signal_from_string (binding_set,
-                                                        scanner->value.v_identifier);
+              ret = gtk_binding_entry_add_signal_from_string (binding_set,
+                                                              scanner->value.v_identifier);
+              if (ret != G_TOKEN_NONE)
+                {
+                  scanner->user_data = "Binding definition";
+                  return ret;
+                }
+
               g_scanner_get_next_token (scanner);
 
               if (scanner->token != ';')